/*     */ package com.zimbra.cs.imap;
/*     */ 
/*     */ import com.google.common.base.Function;
/*     */ import com.google.common.base.Preconditions;
/*     */ import com.google.common.collect.Sets;
/*     */ import com.google.common.util.concurrent.ThreadFactoryBuilder;
/*     */ import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
/*     */ import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap.Builder;
/*     */ import com.zimbra.common.localconfig.DebugConfig;
/*     */ import com.zimbra.common.localconfig.KnownKey;
/*     */ import com.zimbra.common.localconfig.LC;
/*     */ import com.zimbra.common.service.ServiceException;
/*     */ import com.zimbra.common.soap.SoapProtocol;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import com.zimbra.cs.index.SearchParams;
/*     */ import com.zimbra.cs.index.SearchParams.Fetch;
/*     */ import com.zimbra.cs.index.SortBy;
/*     */ import com.zimbra.cs.index.ZimbraHit;
/*     */ import com.zimbra.cs.index.ZimbraQueryResults;
/*     */ import com.zimbra.cs.mailbox.Folder;
/*     */ import com.zimbra.cs.mailbox.MailItem.Type;
/*     */ import com.zimbra.cs.mailbox.Mailbox;
/*     */ import com.zimbra.cs.mailbox.MailboxIndex;
/*     */ import com.zimbra.cs.mailbox.MailboxLock;
/*     */ import com.zimbra.cs.mailbox.MailboxManager;
/*     */ import com.zimbra.cs.mailbox.OperationContext;
/*     */ import com.zimbra.cs.mailbox.SearchFolder;
/*     */ import com.zimbra.cs.mailbox.util.TagUtil;
/*     */ import com.zimbra.cs.memcached.MemcachedConnector;
/*     */ import com.zimbra.cs.session.Session;
/*     */ import com.zimbra.cs.session.Session.Type;
/*     */ import com.zimbra.cs.util.Zimbra;
/*     */ import java.util.ArrayList;
/*     */ import java.util.Collections;
/*     */ import java.util.Iterator;
/*     */ import java.util.List;
/*     */ import java.util.Set;
/*     */ import java.util.Timer;
/*     */ import java.util.TimerTask;
/*     */ import java.util.concurrent.ExecutorService;
/*     */ import java.util.concurrent.Executors;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ final class ImapSessionManager
/*     */ {
/*  59 */   static final long SERIALIZER_INTERVAL_MSEC = DebugConfig.imapSessionSerializerFrequency * 1000L;
/*     */   
/*  61 */   static final long SESSION_INACTIVITY_SERIALIZATION_TIME = DebugConfig.imapSessionInactivitySerializationTime * 1000L;
/*     */   
/*  63 */   static final int TOTAL_SESSION_FOOTPRINT_LIMIT = DebugConfig.imapTotalNonserializedSessionFootprintLimit;
/*  64 */   static final int MAX_NONINTERACTIVE_SESSIONS = DebugConfig.imapNoninteractiveSessionLimit;
/*  65 */   static final boolean CONSISTENCY_CHECK = DebugConfig.imapCacheConsistencyCheck;
/*     */   
/*  67 */   private static final boolean TERMINATE_ON_CLOSE = DebugConfig.imapTerminateSessionOnClose;
/*  68 */   private static final boolean SERIALIZE_ON_CLOSE = DebugConfig.imapSerializeSessionOnClose;
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*  75 */   private final ConcurrentLinkedHashMap<ImapSession, Object> sessions = new ConcurrentLinkedHashMap.Builder().initialCapacity(128).maximumWeightedCapacity(Long.MAX_VALUE).build();
/*     */   
/*     */ 
/*     */   private final Cache activeSessionCache;
/*     */   
/*     */ 
/*     */   private final Cache inactiveSessionCache;
/*     */   
/*  83 */   private static final ImapSessionManager SINGLETON = new ImapSessionManager();
/*     */   
/*  85 */   private static final ExecutorService CLOSER = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat("ImapInvalidSessionCloser").setDaemon(true).build());
/*     */   
/*     */   private ImapSessionManager()
/*     */   {
/*  89 */     if (SERIALIZER_INTERVAL_MSEC > 0L) {
/*  90 */       Zimbra.sTimer.schedule(new SessionSerializerTask(), SERIALIZER_INTERVAL_MSEC, SERIALIZER_INTERVAL_MSEC);
/*  91 */       ZimbraLog.imap.debug("initializing IMAP session serializer task");
/*     */     }
/*  93 */     if (LC.imap_use_ehcache.booleanValue()) {
/*  94 */       this.activeSessionCache = new EhcacheImapCache("imap-active-session-cache", true);
/*  95 */       Preconditions.checkState(this.activeSessionCache != null);
/*     */     } else {
/*  97 */       this.activeSessionCache = new DiskImapCache();
/*     */     }
/*     */     
/* 100 */     this.inactiveSessionCache = (LC.imap_use_ehcache.booleanValue() ? new EhcacheImapCache("imap-inactive-session-cache", false) : MemcachedConnector.isConnected() ? new MemcachedImapCache() : this.activeSessionCache);
/*     */     
/*     */ 
/*     */ 
/* 104 */     Preconditions.checkState(this.inactiveSessionCache != null);
/*     */   }
/*     */   
/*     */   static ImapSessionManager getInstance() {
/* 108 */     return SINGLETON;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   void recordAccess(ImapSession session)
/*     */   {
/* 118 */     this.sessions.get(session);
/*     */   }
/*     */   
/*     */   void uncacheSession(ImapSession session) {
/* 122 */     this.sessions.remove(session);
/*     */   }
/*     */   
/*     */   /* Error */
/*     */   com.zimbra.common.util.Pair<ImapSession, InitialFolderValues> openFolder(ImapPath path, byte params, ImapHandler handler)
/*     */     throws ServiceException
/*     */   {
/*     */     // Byte code:
/*     */     //   0: getstatic 16	com/zimbra/common/util/ZimbraLog:imap	Lcom/zimbra/common/util/Log;
/*     */     //   3: ldc 36
/*     */     //   5: iconst_1
/*     */     //   6: anewarray 37	java/lang/Object
/*     */     //   9: dup
/*     */     //   10: iconst_0
/*     */     //   11: aload_1
/*     */     //   12: aastore
/*     */     //   13: invokevirtual 38	com/zimbra/common/util/Log:debug	(Ljava/lang/String;[Ljava/lang/Object;)V
/*     */     //   16: aload_1
/*     */     //   17: invokevirtual 39	com/zimbra/cs/imap/ImapPath:isSelectable	()Z
/*     */     //   20: ifne +26 -> 46
/*     */     //   23: new 40	java/lang/StringBuilder
/*     */     //   26: dup
/*     */     //   27: invokespecial 41	java/lang/StringBuilder:<init>	()V
/*     */     //   30: ldc 42
/*     */     //   32: invokevirtual 43	java/lang/StringBuilder:append	(Ljava/lang/String;)Ljava/lang/StringBuilder;
/*     */     //   35: aload_1
/*     */     //   36: invokevirtual 44	java/lang/StringBuilder:append	(Ljava/lang/Object;)Ljava/lang/StringBuilder;
/*     */     //   39: invokevirtual 45	java/lang/StringBuilder:toString	()Ljava/lang/String;
/*     */     //   42: invokestatic 46	com/zimbra/common/service/ServiceException:PERM_DENIED	(Ljava/lang/String;)Lcom/zimbra/common/service/ServiceException;
/*     */     //   45: athrow
/*     */     //   46: iload_2
/*     */     //   47: iconst_2
/*     */     //   48: iand
/*     */     //   49: ifeq +10 -> 59
/*     */     //   52: aload_3
/*     */     //   53: getstatic 47	com/zimbra/cs/imap/ImapHandler$ImapExtension:CONDSTORE	Lcom/zimbra/cs/imap/ImapHandler$ImapExtension;
/*     */     //   56: invokevirtual 48	com/zimbra/cs/imap/ImapHandler:activateExtension	(Lcom/zimbra/cs/imap/ImapHandler$ImapExtension;)V
/*     */     //   59: aload_1
/*     */     //   60: invokevirtual 49	com/zimbra/cs/imap/ImapPath:getFolder	()Ljava/lang/Object;
/*     */     //   63: checkcast 50	com/zimbra/cs/mailbox/Folder
/*     */     //   66: astore 4
/*     */     //   68: aload 4
/*     */     //   70: invokevirtual 51	com/zimbra/cs/mailbox/Folder:getId	()I
/*     */     //   73: istore 5
/*     */     //   75: aload 4
/*     */     //   77: invokevirtual 52	com/zimbra/cs/mailbox/Folder:getMailbox	()Lcom/zimbra/cs/mailbox/Mailbox;
/*     */     //   80: astore 6
/*     */     //   82: aload_3
/*     */     //   83: invokevirtual 53	com/zimbra/cs/imap/ImapHandler:getCredentials	()Lcom/zimbra/cs/imap/ImapCredentials;
/*     */     //   86: invokevirtual 54	com/zimbra/cs/imap/ImapCredentials:getContext	()Lcom/zimbra/cs/mailbox/OperationContext;
/*     */     //   89: astore 7
/*     */     //   91: aload 6
/*     */     //   93: invokevirtual 55	com/zimbra/cs/mailbox/Mailbox:beginTrackingImap	()V
/*     */     //   96: aconst_null
/*     */     //   97: astore 8
/*     */     //   99: aload 4
/*     */     //   101: instanceof 56
/*     */     //   104: ifeq +15 -> 119
/*     */     //   107: aload 7
/*     */     //   109: aload 4
/*     */     //   111: checkcast 56	com/zimbra/cs/mailbox/SearchFolder
/*     */     //   114: invokestatic 57	com/zimbra/cs/imap/ImapSessionManager:loadVirtualFolder	(Lcom/zimbra/cs/mailbox/OperationContext;Lcom/zimbra/cs/mailbox/SearchFolder;)Ljava/util/List;
/*     */     //   117: astore 8
/*     */     //   119: aload 6
/*     */     //   121: getfield 58	com/zimbra/cs/mailbox/Mailbox:lock	Lcom/zimbra/cs/mailbox/MailboxLock;
/*     */     //   124: invokevirtual 59	com/zimbra/cs/mailbox/MailboxLock:lock	()V
/*     */     //   127: aload 6
/*     */     //   129: aload 7
/*     */     //   131: iload 5
/*     */     //   133: invokevirtual 60	com/zimbra/cs/mailbox/Mailbox:getFolderById	(Lcom/zimbra/cs/mailbox/OperationContext;I)Lcom/zimbra/cs/mailbox/Folder;
/*     */     //   136: astore 4
/*     */     //   138: aload 4
/*     */     //   140: invokevirtual 61	com/zimbra/cs/mailbox/Folder:getImapRECENTCutoff	()I
/*     */     //   143: istore 9
/*     */     //   145: aload 8
/*     */     //   147: ifnonnull +85 -> 232
/*     */     //   150: aload 6
/*     */     //   152: getstatic 62	com/zimbra/cs/session/Session$Type:IMAP	Lcom/zimbra/cs/session/Session$Type;
/*     */     //   155: invokevirtual 63	com/zimbra/cs/mailbox/Mailbox:getListeners	(Lcom/zimbra/cs/session/Session$Type;)Ljava/util/List;
/*     */     //   158: astore 10
/*     */     //   160: iload 5
/*     */     //   162: aload 10
/*     */     //   164: invokestatic 64	com/zimbra/cs/imap/ImapSessionManager:duplicateExistingSession	(ILjava/util/List;)Ljava/util/List;
/*     */     //   167: astore 8
/*     */     //   169: aload 8
/*     */     //   171: ifnonnull +14 -> 185
/*     */     //   174: aload_0
/*     */     //   175: aload 4
/*     */     //   177: invokespecial 65	com/zimbra/cs/imap/ImapSessionManager:duplicateSerializedFolder	(Lcom/zimbra/cs/mailbox/Folder;)Ljava/util/List;
/*     */     //   180: astore 8
/*     */     //   182: goto +14 -> 196
/*     */     //   185: getstatic 66	com/zimbra/cs/imap/ImapSessionManager:CONSISTENCY_CHECK	Z
/*     */     //   188: ifeq +8 -> 196
/*     */     //   191: aload 8
/*     */     //   193: invokestatic 67	java/util/Collections:sort	(Ljava/util/List;)V
/*     */     //   196: getstatic 66	com/zimbra/cs/imap/ImapSessionManager:CONSISTENCY_CHECK	Z
/*     */     //   199: ifeq +17 -> 216
/*     */     //   202: aload_0
/*     */     //   203: aload 8
/*     */     //   205: aload 6
/*     */     //   207: aload 7
/*     */     //   209: aload 4
/*     */     //   211: invokespecial 68	com/zimbra/cs/imap/ImapSessionManager:consistencyCheck	(Ljava/util/List;Lcom/zimbra/cs/mailbox/Mailbox;Lcom/zimbra/cs/mailbox/OperationContext;Lcom/zimbra/cs/mailbox/Folder;)Ljava/util/List;
/*     */     //   214: astore 8
/*     */     //   216: aload 8
/*     */     //   218: ifnonnull +14 -> 232
/*     */     //   221: aload 6
/*     */     //   223: aload 7
/*     */     //   225: iload 5
/*     */     //   227: invokevirtual 69	com/zimbra/cs/mailbox/Mailbox:openImapFolder	(Lcom/zimbra/cs/mailbox/OperationContext;I)Ljava/util/List;
/*     */     //   230: astore 8
/*     */     //   232: aload 8
/*     */     //   234: invokestatic 67	java/util/Collections:sort	(Ljava/util/List;)V
/*     */     //   237: aload 7
/*     */     //   239: aload 6
/*     */     //   241: aload 8
/*     */     //   243: invokestatic 70	com/zimbra/cs/imap/ImapSessionManager:renumberMessages	(Lcom/zimbra/cs/mailbox/OperationContext;Lcom/zimbra/cs/mailbox/Mailbox;Ljava/util/List;)V
/*     */     //   246: new 71	com/zimbra/cs/imap/ImapFolder
/*     */     //   249: dup
/*     */     //   250: aload_1
/*     */     //   251: iload_2
/*     */     //   252: aload_3
/*     */     //   253: invokespecial 72	com/zimbra/cs/imap/ImapFolder:<init>	(Lcom/zimbra/cs/imap/ImapPath;BLcom/zimbra/cs/imap/ImapHandler;)V
/*     */     //   256: astore 10
/*     */     //   258: aload 6
/*     */     //   260: aload 7
/*     */     //   262: iload 5
/*     */     //   264: invokevirtual 60	com/zimbra/cs/mailbox/Mailbox:getFolderById	(Lcom/zimbra/cs/mailbox/OperationContext;I)Lcom/zimbra/cs/mailbox/Folder;
/*     */     //   267: astore 4
/*     */     //   269: new 73	com/zimbra/cs/imap/ImapSessionManager$InitialFolderValues
/*     */     //   272: dup
/*     */     //   273: aload 4
/*     */     //   275: invokespecial 74	com/zimbra/cs/imap/ImapSessionManager$InitialFolderValues:<init>	(Lcom/zimbra/cs/mailbox/Folder;)V
/*     */     //   278: astore 11
/*     */     //   280: aload 8
/*     */     //   282: invokeinterface 75 1 0
/*     */     //   287: astore 12
/*     */     //   289: aload 12
/*     */     //   291: invokeinterface 76 1 0
/*     */     //   296: ifeq +72 -> 368
/*     */     //   299: aload 12
/*     */     //   301: invokeinterface 77 1 0
/*     */     //   306: checkcast 78	com/zimbra/cs/imap/ImapMessage
/*     */     //   309: astore 13
/*     */     //   311: aload 10
/*     */     //   313: aload 13
/*     */     //   315: aload 13
/*     */     //   317: getfield 79	com/zimbra/cs/imap/ImapMessage:imapUid	I
/*     */     //   320: iload 9
/*     */     //   322: if_icmple +7 -> 329
/*     */     //   325: iconst_1
/*     */     //   326: goto +4 -> 330
/*     */     //   329: iconst_0
/*     */     //   330: invokevirtual 80	com/zimbra/cs/imap/ImapFolder:cache	(Lcom/zimbra/cs/imap/ImapMessage;Z)Z
/*     */     //   333: pop
/*     */     //   334: aload 11
/*     */     //   336: getfield 81	com/zimbra/cs/imap/ImapSessionManager$InitialFolderValues:firstUnread	I
/*     */     //   339: iconst_m1
/*     */     //   340: if_icmpne +25 -> 365
/*     */     //   343: aload 13
/*     */     //   345: getfield 82	com/zimbra/cs/imap/ImapMessage:flags	I
/*     */     //   348: getstatic 83	com/zimbra/cs/mailbox/Flag:BITMASK_UNREAD	I
/*     */     //   351: iand
/*     */     //   352: ifeq +13 -> 365
/*     */     //   355: aload 11
/*     */     //   357: aload 13
/*     */     //   359: getfield 84	com/zimbra/cs/imap/ImapMessage:sequence	I
/*     */     //   362: putfield 81	com/zimbra/cs/imap/ImapSessionManager$InitialFolderValues:firstUnread	I
/*     */     //   365: goto -76 -> 289
/*     */     //   368: aload 10
/*     */     //   370: invokevirtual 85	com/zimbra/cs/imap/ImapFolder:setInitialSize	()V
/*     */     //   373: getstatic 16	com/zimbra/common/util/ZimbraLog:imap	Lcom/zimbra/common/util/Log;
/*     */     //   376: ldc 86
/*     */     //   378: iconst_1
/*     */     //   379: anewarray 37	java/lang/Object
/*     */     //   382: dup
/*     */     //   383: iconst_0
/*     */     //   384: aload 8
/*     */     //   386: aastore
/*     */     //   387: invokevirtual 38	com/zimbra/common/util/Log:debug	(Ljava/lang/String;[Ljava/lang/Object;)V
/*     */     //   390: aconst_null
/*     */     //   391: astore 12
/*     */     //   393: new 87	com/zimbra/cs/imap/ImapSession
/*     */     //   396: dup
/*     */     //   397: aload 10
/*     */     //   399: aload_3
/*     */     //   400: invokespecial 88	com/zimbra/cs/imap/ImapSession:<init>	(Lcom/zimbra/cs/imap/ImapFolder;Lcom/zimbra/cs/imap/ImapHandler;)V
/*     */     //   403: astore 12
/*     */     //   405: aload 12
/*     */     //   407: invokevirtual 89	com/zimbra/cs/imap/ImapSession:register	()Lcom/zimbra/cs/session/Session;
/*     */     //   410: pop
/*     */     //   411: aload_0
/*     */     //   412: getfield 2	com/zimbra/cs/imap/ImapSessionManager:sessions	Lcom/googlecode/concurrentlinkedhashmap/ConcurrentLinkedHashMap;
/*     */     //   415: aload 12
/*     */     //   417: aload 12
/*     */     //   419: invokevirtual 90	com/googlecode/concurrentlinkedhashmap/ConcurrentLinkedHashMap:put	(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
/*     */     //   422: pop
/*     */     //   423: new 91	com/zimbra/common/util/Pair
/*     */     //   426: dup
/*     */     //   427: aload 12
/*     */     //   429: aload 11
/*     */     //   431: invokespecial 92	com/zimbra/common/util/Pair:<init>	(Ljava/lang/Object;Ljava/lang/Object;)V
/*     */     //   434: astore 13
/*     */     //   436: aload 6
/*     */     //   438: getfield 58	com/zimbra/cs/mailbox/Mailbox:lock	Lcom/zimbra/cs/mailbox/MailboxLock;
/*     */     //   441: invokevirtual 93	com/zimbra/cs/mailbox/MailboxLock:release	()V
/*     */     //   444: aload 13
/*     */     //   446: areturn
/*     */     //   447: astore 13
/*     */     //   449: aload 12
/*     */     //   451: ifnull +9 -> 460
/*     */     //   454: aload 12
/*     */     //   456: invokevirtual 95	com/zimbra/cs/imap/ImapSession:unregister	()Lcom/zimbra/cs/session/Session;
/*     */     //   459: pop
/*     */     //   460: aload 13
/*     */     //   462: athrow
/*     */     //   463: astore 14
/*     */     //   465: aload 6
/*     */     //   467: getfield 58	com/zimbra/cs/mailbox/Mailbox:lock	Lcom/zimbra/cs/mailbox/MailboxLock;
/*     */     //   470: invokevirtual 93	com/zimbra/cs/mailbox/MailboxLock:release	()V
/*     */     //   473: aload 14
/*     */     //   475: athrow
/*     */     // Line number table:
/*     */     //   Java source line #252	-> byte code offset #0
/*     */     //   Java source line #254	-> byte code offset #16
/*     */     //   Java source line #255	-> byte code offset #23
/*     */     //   Java source line #257	-> byte code offset #46
/*     */     //   Java source line #258	-> byte code offset #52
/*     */     //   Java source line #261	-> byte code offset #59
/*     */     //   Java source line #262	-> byte code offset #68
/*     */     //   Java source line #263	-> byte code offset #75
/*     */     //   Java source line #265	-> byte code offset #82
/*     */     //   Java source line #267	-> byte code offset #91
/*     */     //   Java source line #269	-> byte code offset #96
/*     */     //   Java source line #271	-> byte code offset #99
/*     */     //   Java source line #272	-> byte code offset #107
/*     */     //   Java source line #275	-> byte code offset #119
/*     */     //   Java source line #278	-> byte code offset #127
/*     */     //   Java source line #279	-> byte code offset #138
/*     */     //   Java source line #281	-> byte code offset #145
/*     */     //   Java source line #282	-> byte code offset #150
/*     */     //   Java source line #285	-> byte code offset #160
/*     */     //   Java source line #287	-> byte code offset #169
/*     */     //   Java source line #288	-> byte code offset #174
/*     */     //   Java source line #289	-> byte code offset #185
/*     */     //   Java source line #290	-> byte code offset #191
/*     */     //   Java source line #295	-> byte code offset #196
/*     */     //   Java source line #296	-> byte code offset #202
/*     */     //   Java source line #299	-> byte code offset #216
/*     */     //   Java source line #300	-> byte code offset #221
/*     */     //   Java source line #304	-> byte code offset #232
/*     */     //   Java source line #306	-> byte code offset #237
/*     */     //   Java source line #308	-> byte code offset #246
/*     */     //   Java source line #311	-> byte code offset #258
/*     */     //   Java source line #313	-> byte code offset #269
/*     */     //   Java source line #315	-> byte code offset #280
/*     */     //   Java source line #316	-> byte code offset #311
/*     */     //   Java source line #317	-> byte code offset #334
/*     */     //   Java source line #318	-> byte code offset #355
/*     */     //   Java source line #320	-> byte code offset #365
/*     */     //   Java source line #321	-> byte code offset #368
/*     */     //   Java source line #322	-> byte code offset #373
/*     */     //   Java source line #324	-> byte code offset #390
/*     */     //   Java source line #326	-> byte code offset #393
/*     */     //   Java source line #327	-> byte code offset #405
/*     */     //   Java source line #328	-> byte code offset #411
/*     */     //   Java source line #329	-> byte code offset #423
/*     */     //   Java source line #337	-> byte code offset #436
/*     */     //   Java source line #330	-> byte code offset #447
/*     */     //   Java source line #331	-> byte code offset #449
/*     */     //   Java source line #332	-> byte code offset #454
/*     */     //   Java source line #334	-> byte code offset #460
/*     */     //   Java source line #337	-> byte code offset #463
/*     */     // Local variable table:
/*     */     //   start	length	slot	name	signature
/*     */     //   0	476	0	this	ImapSessionManager
/*     */     //   0	476	1	path	ImapPath
/*     */     //   0	476	2	params	byte
/*     */     //   0	476	3	handler	ImapHandler
/*     */     //   66	208	4	folder	Folder
/*     */     //   73	190	5	folderId	int
/*     */     //   80	386	6	mbox	Mailbox
/*     */     //   89	172	7	octxt	OperationContext
/*     */     //   97	288	8	i4list	List<ImapMessage>
/*     */     //   143	178	9	recentCutoff	int
/*     */     //   158	5	10	listeners	List<Session>
/*     */     //   256	142	10	i4folder	ImapFolder
/*     */     //   278	152	11	initial	InitialFolderValues
/*     */     //   287	13	12	i$	Iterator
/*     */     //   391	64	12	session	ImapSession
/*     */     //   309	136	13	i4msg	ImapMessage
/*     */     //   447	14	13	e	ServiceException
/*     */     //   463	11	14	localObject	Object
/*     */     // Exception table:
/*     */     //   from	to	target	type
/*     */     //   393	436	447	com/zimbra/common/service/ServiceException
/*     */     //   127	436	463	finally
/*     */     //   447	465	463	finally
/*     */   }
/*     */   
/*     */   final class SessionSerializerTask
/*     */     extends TimerTask
/*     */   {
/*     */     SessionSerializerTask() {}
/*     */     
/*     */     public void run()
/*     */     {
/* 137 */       ZimbraLog.imap.debug("running IMAP session serializer task");
/*     */       try
/*     */       {
/* 140 */         long cutoff = ImapSessionManager.SESSION_INACTIVITY_SERIALIZATION_TIME > 0L ? System.currentTimeMillis() - ImapSessionManager.SESSION_INACTIVITY_SERIALIZATION_TIME : Long.MIN_VALUE;
/*     */         
/*     */ 
/* 143 */         List<ImapSession> overflow = new ArrayList();
/* 144 */         List<ImapSession> pageable = new ArrayList();
/* 145 */         List<ImapSession> droppable = new ArrayList();
/*     */         
/*     */ 
/* 148 */         int maxOverflow = 0;
/* 149 */         Iterator<ImapSession> unorderedIterator = ImapSessionManager.this.sessions.keySet().iterator();
/* 150 */         while (unorderedIterator.hasNext()) {
/* 151 */           ImapSession session = (ImapSession)unorderedIterator.next();
/* 152 */           if (session.requiresReload()) {
/* 153 */             overflow.add(session);
/*     */             
/* 155 */             maxOverflow = Math.max(maxOverflow, session.getEstimatedSize());
/*     */           }
/*     */         }
/* 158 */         int footprint = Math.min(maxOverflow, ImapSessionManager.TOTAL_SESSION_FOOTPRINT_LIMIT - 1000);
/* 159 */         int noninteractive = 0;
/*     */         
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/* 165 */         Iterator<ImapSession> mostRecentToLeastRecentIterator = ImapSessionManager.this.sessions.descendingKeySet().iterator();
/* 166 */         label287: while (mostRecentToLeastRecentIterator.hasNext()) {
/* 167 */           ImapSession session = (ImapSession)mostRecentToLeastRecentIterator.next();
/* 168 */           int size = session.getEstimatedSize();
/*     */           
/*     */ 
/* 171 */           if (!session.isInteractive()) { noninteractive++; if (noninteractive > ImapSessionManager.MAX_NONINTERACTIVE_SESSIONS) {
/* 172 */               droppable.add(session);
/* 173 */               break label287; } } if ((!session.isSerialized()) && (session.getLastAccessTime() < cutoff)) {
/* 174 */             pageable.add(session);
/* 175 */           } else if (footprint + size > ImapSessionManager.TOTAL_SESSION_FOOTPRINT_LIMIT) {
/* 176 */             pageable.add(session);
/*     */           } else {
/* 178 */             footprint += size;
/*     */           }
/*     */         }
/*     */         
/* 182 */         for (ImapSession session : pageable) {
/*     */           try {
/* 184 */             ZimbraLog.imap.debug("Paging out session due to staleness or total memory footprint: %s (sid %s)", new Object[] { session.getPath(), session.getSessionId() });
/*     */             
/* 186 */             session.unload(true);
/*     */           } catch (Exception e) {
/* 188 */             ZimbraLog.imap.warn("error serializing session; clearing", e);
/*     */             
/* 190 */             quietRemoveSession(session);
/*     */           }
/*     */         }
/*     */         
/* 194 */         for (ImapSession session : overflow) {
/*     */           try {
/* 196 */             ZimbraLog.imap.debug("Loading/unloading paged session due to queued notification overflow: %s (sid %s)", new Object[] { session.getPath(), session.getSessionId() });
/*     */             
/* 198 */             if ((session.reload() instanceof ImapFolder)) {
/* 199 */               session.unload(true);
/*     */             } else {
/* 201 */               ZimbraLog.imap.debug("unable to reload session during paged overflow replay; probably evicted from cache");
/* 202 */               quietRemoveSession(session);
/*     */             }
/*     */           }
/*     */           catch (ImapSessionClosedException ignore) {}catch (Exception e) {
/* 206 */             ZimbraLog.imap.warn("error deserializing overflowed session; clearing", e);
/*     */             
/* 208 */             quietRemoveSession(session);
/*     */           }
/*     */         }
/*     */         
/* 212 */         for (ImapSession session : droppable) {
/* 213 */           ZimbraLog.imap.debug("Removing session due to having too many noninteractive sessions: %s (sid %s)", new Object[] { session.getPath(), session.getSessionId() });
/*     */           
/*     */ 
/* 216 */           quietRemoveSession(session);
/*     */         }
/*     */       } catch (Throwable t) {
/* 219 */         ZimbraLog.imap.warn("Error during IMAP session serializer task", t);
/*     */       }
/*     */     }
/*     */     
/*     */     private void quietRemoveSession(final ImapSession session)
/*     */     {
/*     */       try {
/* 226 */         if (session.isInteractive()) {
/* 227 */           ImapSessionManager.CLOSER.submit(new Runnable()
/*     */           {
/*     */             public void run() {
/* 230 */               session.cleanup();
/*     */             }
/*     */           });
/*     */         }
/* 234 */         session.detach();
/*     */       } catch (Exception e) {
/* 236 */         ZimbraLog.imap.warn("skipping error while trying to remove session", e);
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */   static class InitialFolderValues { final int uidnext;
/*     */     final int modseq;
/* 243 */     int firstUnread = -1;
/*     */     
/*     */     InitialFolderValues(Folder folder) {
/* 246 */       this.uidnext = folder.getImapUIDNEXT();
/* 247 */       this.modseq = folder.getImapMODSEQ();
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   private static List<ImapMessage> loadVirtualFolder(OperationContext octxt, SearchFolder search)
/*     */     throws ServiceException
/*     */   {
/* 349 */     List<ImapMessage> i4list = new ArrayList();
/*     */     
/* 351 */     Set<MailItem.Type> types = ImapFolder.getTypeConstraint(search);
/* 352 */     if (types.isEmpty()) {
/* 353 */       return i4list;
/*     */     }
/*     */     
/* 356 */     SearchParams params = new SearchParams();
/* 357 */     params.setQueryString(search.getQuery());
/* 358 */     params.setIncludeTagDeleted(true);
/* 359 */     params.setTypes(types);
/* 360 */     params.setSortBy(SortBy.DATE_ASC);
/* 361 */     params.setChunkSize(1000);
/* 362 */     params.setFetchMode(SearchParams.Fetch.IMAP);
/*     */     
/* 364 */     Mailbox mbox = search.getMailbox();
/*     */     try {
/* 366 */       ZimbraQueryResults zqr = mbox.index.search(SoapProtocol.Soap12, octxt, params);
/*     */       try {
/* 368 */         for (ZimbraHit hit = zqr.getNext(); hit != null; hit = zqr.getNext()) {
/* 369 */           i4list.add(hit.getImapMessage());
/*     */         }
/*     */       } finally {
/* 372 */         zqr.close();
/*     */       }
/*     */     } catch (ServiceException e) {
/* 375 */       throw e;
/*     */     } catch (Exception e) {
/* 377 */       throw ServiceException.FAILURE("failure opening search folder", e);
/*     */     }
/* 379 */     return i4list;
/*     */   }
/*     */   
/*     */   private static List<ImapMessage> duplicateExistingSession(int folderId, List<Session> sessionList) {
/* 383 */     for (Session session : sessionList) {
/* 384 */       ImapSession i4listener = (ImapSession)session;
/* 385 */       if (i4listener.getFolderId() == folderId)
/*     */       {
/* 387 */         synchronized (i4listener) {
/*     */           ImapFolder i4selected;
/*     */           try {
/* 390 */             i4selected = i4listener.getImapFolder();
/*     */           } catch (ImapSessionClosedException e) {
/* 392 */             return null;
/*     */           }
/* 394 */           if (i4selected == null) {
/* 395 */             return null;
/*     */           }
/*     */           
/* 398 */           ZimbraLog.imap.info("copying message data from existing session: %s", new Object[] { i4listener.getPath() });
/*     */           
/* 400 */           List<ImapMessage> i4list = new ArrayList(i4selected.getSize());
/* 401 */           i4selected.traverse(new Function()
/*     */           {
/*     */             public Void apply(ImapMessage i4msg) {
/* 404 */               if (!i4msg.isExpunged()) {
/* 405 */                 this.val$i4list.add(new ImapMessage(i4msg));
/*     */               }
/* 407 */               return null;
/*     */             }
/*     */           });
/*     */           
/*     */ 
/*     */ 
/* 413 */           if (!i4listener.isInteractive()) {
/* 414 */             i4listener.unregister();
/*     */           }
/* 416 */           return i4list;
/*     */         }
/*     */       }
/*     */     }
/* 420 */     return null;
/*     */   }
/*     */   
/*     */   private List<ImapMessage> duplicateSerializedFolder(Folder folder) {
/* 424 */     ImapFolder i4folder = getCache(folder);
/* 425 */     if (i4folder == null) {
/* 426 */       return null;
/*     */     }
/* 428 */     ZimbraLog.imap.info("copying message data from serialized session: %s", new Object[] { folder.getPath() });
/*     */     
/* 430 */     final List<ImapMessage> i4list = new ArrayList(i4folder.getSize());
/* 431 */     i4folder.traverse(new Function()
/*     */     {
/*     */       public Void apply(ImapMessage i4msg) {
/* 434 */         if (!i4msg.isExpunged()) {
/* 435 */           i4list.add(i4msg.reset());
/*     */         }
/* 437 */         return null;
/*     */       }
/* 439 */     });
/* 440 */     return i4list;
/*     */   }
/*     */   
/*     */   private List<ImapMessage> consistencyCheck(List<ImapMessage> i4list, Mailbox mbox, OperationContext octxt, Folder folder) {
/* 444 */     if (i4list == null) {
/* 445 */       return i4list;
/*     */     }
/*     */     
/* 448 */     String fid = mbox.getAccountId() + ":" + folder.getId();
/*     */     try {
/* 450 */       List<ImapMessage> actual = mbox.openImapFolder(octxt, folder.getId());
/* 451 */       Collections.sort(actual);
/* 452 */       if (i4list.size() != actual.size()) {
/* 453 */         ZimbraLog.imap.error("IMAP session cache consistency check failed: inconsistent list lengths folder=%s,cache=%d,db=%d,diff={cache:%s,db:%s},dupes=%s", new Object[] { fid, Integer.valueOf(i4list.size()), Integer.valueOf(actual.size()), diff(i4list, actual), diff(actual, i4list), dupeCheck(i4list) });
/*     */         
/*     */ 
/* 456 */         clearCache(folder);
/* 457 */         return actual;
/*     */       }
/*     */       
/* 460 */       Iterator<ImapMessage> it1 = i4list.iterator(); for (Iterator<ImapMessage> it2 = actual.iterator(); (it1.hasNext()) || (it2.hasNext());) {
/* 461 */         ImapMessage msg1 = (ImapMessage)it1.next();ImapMessage msg2 = (ImapMessage)it2.next();
/* 462 */         if ((msg1.msgId != msg2.msgId) || (msg1.imapUid != msg2.imapUid)) {
/* 463 */           ZimbraLog.imap.error("IMAP session cache consistency check failed: id mismatch folder=%s,cache=%d/%d,db=%d/%d,diff={cache:%s,db:%s}", new Object[] { fid, Integer.valueOf(msg1.msgId), Integer.valueOf(msg1.imapUid), Integer.valueOf(msg2.msgId), Integer.valueOf(msg2.imapUid), diff(i4list, actual), diff(actual, i4list) });
/*     */           
/*     */ 
/*     */ 
/* 467 */           clearCache(folder);
/* 468 */           return actual; }
/* 469 */         if ((msg1.flags != msg2.flags) || (msg1.sflags != msg2.sflags) || (!TagUtil.tagsMatch(msg1.tags, msg2.tags))) {
/* 470 */           ZimbraLog.imap.error("IMAP session cache consistency check failed: flag/tag/sflag mismatch folder=%s,cache=%X/[%s]/%X,db=%X/[%s]/%X,diff={cache:%s,db:%s}", new Object[] { fid, Integer.valueOf(msg1.flags), TagUtil.encodeTags(msg1.tags), Short.valueOf(msg1.sflags), Integer.valueOf(msg2.flags), TagUtil.encodeTags(msg2.tags), Short.valueOf(msg2.sflags), diff(i4list, actual), diff(actual, i4list) });
/*     */           
/*     */ 
/*     */ 
/*     */ 
/* 475 */           clearCache(folder);
/* 476 */           return actual;
/*     */         }
/*     */       }
/* 479 */       return i4list;
/*     */     } catch (ServiceException e) {
/* 481 */       ZimbraLog.imap.info("  ** error caught during IMAP session cache consistency check; falling back to reload", e);
/* 482 */       clearCache(folder); }
/* 483 */     return null;
/*     */   }
/*     */   
/*     */   private Set<ImapMessage> diff(List<ImapMessage> list1, List<ImapMessage> list2)
/*     */   {
/* 488 */     Set<ImapMessage> diff = Sets.newHashSet(list1);
/* 489 */     diff.removeAll(list2);
/* 490 */     return diff;
/*     */   }
/*     */   
/*     */   private List<ImapMessage> dupeCheck(List<ImapMessage> list) {
/* 494 */     List<ImapMessage> dupes = new ArrayList();
/* 495 */     for (int i = 0; i < list.size(); i++) {
/* 496 */       ImapMessage current = (ImapMessage)list.get(i);
/* 497 */       if ((dupes.contains(current)) || (list.lastIndexOf(current) != i)) {
/* 498 */         dupes.add(current);
/*     */       }
/*     */     }
/* 501 */     return dupes;
/*     */   }
/*     */   
/*     */   private static void renumberMessages(OperationContext octxt, Mailbox mbox, List<ImapMessage> i4sorted) throws ServiceException
/*     */   {
/* 506 */     List<ImapMessage> unnumbered = new ArrayList();
/* 507 */     List<Integer> renumber = new ArrayList();
/* 508 */     ImapMessage i4msg; for (; (!i4sorted.isEmpty()) && (((ImapMessage)i4sorted.get(0)).imapUid <= 0); 
/*     */         
/* 510 */         renumber.add(Integer.valueOf(i4msg.msgId)))
/*     */     {
/* 509 */       i4msg = (ImapMessage)i4sorted.remove(0);
/* 510 */       unnumbered.add(i4msg);
/*     */     }
/* 512 */     if (!renumber.isEmpty()) {
/* 513 */       List<Integer> newIds = mbox.resetImapUid(octxt, renumber);
/* 514 */       for (int i = 0; i < newIds.size(); i++) {
/* 515 */         ((ImapMessage)unnumbered.get(i)).imapUid = ((Integer)newIds.get(i)).intValue();
/*     */       }
/* 517 */       i4sorted.addAll(unnumbered);
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   void closeFolder(ImapSession session, boolean isUnregistering)
/*     */   {
/* 525 */     if (session.isInteractive()) {
/* 526 */       session.inactivate();
/*     */     }
/*     */     
/*     */ 
/* 530 */     if (session.isVirtual()) {
/* 531 */       session.detach();
/* 532 */       return;
/*     */     }
/*     */     
/*     */ 
/* 536 */     if (SERIALIZE_ON_CLOSE) {
/*     */       try
/*     */       {
/* 539 */         ZimbraLog.imap.debug("Paging session during close: %s", new Object[] { session.getPath() });
/* 540 */         session.unload(false);
/*     */       } catch (Exception e) {
/* 542 */         ZimbraLog.imap.warn("Skipping error while trying to serialize during close (%s)", session.getPath(), e);
/*     */       }
/*     */     }
/*     */     
/* 546 */     if (isUnregistering) {
/* 547 */       return;
/*     */     }
/*     */     
/*     */ 
/* 551 */     if (TERMINATE_ON_CLOSE) {
/* 552 */       session.detach();
/* 553 */       return;
/*     */     }
/*     */     
/*     */ 
/* 557 */     Mailbox mbox = session.getMailbox();
/* 558 */     if (mbox != null) {
/* 559 */       mbox.lock.lock();
/*     */       try {
/* 561 */         for (Iterator i$ = mbox.getListeners(Session.Type.IMAP).iterator(); i$.hasNext(); return) { Session listener = (Session)i$.next();
/* 562 */           ImapSession i4listener = (ImapSession)listener;
/* 563 */           if ((i4listener != session) && (i4listener.getFolderId() == session.getFolderId())) {
/* 564 */             session.detach();
/* 565 */             recordAccess(i4listener);
/*     */           }
/*     */         }
/*     */       }
/*     */       finally {
/* 570 */         mbox.lock.release();
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   private ImapFolder getCache(Folder folder)
/*     */   {
/* 579 */     ImapFolder i4folder = this.inactiveSessionCache.get(cacheKey(folder, false));
/* 580 */     if (i4folder != null) {
/* 581 */       return i4folder;
/*     */     }
/* 583 */     return this.activeSessionCache.get(cacheKey(folder, true));
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   private void clearCache(Folder folder)
/*     */   {
/* 590 */     this.activeSessionCache.remove(cacheKey(folder, true));
/* 591 */     this.inactiveSessionCache.remove(cacheKey(folder, false));
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   String cacheKey(ImapSession session, boolean active)
/*     */     throws ServiceException
/*     */   {
/* 602 */     Mailbox mbox = session.getMailbox();
/* 603 */     if (mbox == null) {
/* 604 */       mbox = MailboxManager.getInstance().getMailboxByAccountId(session.getTargetAccountId());
/*     */     }
/*     */     
/* 607 */     String cachekey = cacheKey(mbox.getFolderById(null, session.getFolderId()), active);
/*     */     
/*     */ 
/* 610 */     return session.hasExpunges() ? cachekey + "+" + session.getQualifiedSessionId() : cachekey;
/*     */   }
/*     */   
/*     */   private String cacheKey(Folder folder, boolean active) {
/* 614 */     Mailbox mbox = folder.getMailbox();
/* 615 */     int modseq = (folder instanceof SearchFolder) ? mbox.getLastChangeID() : folder.getImapMODSEQ();
/* 616 */     int uvv = (folder instanceof SearchFolder) ? mbox.getLastChangeID() : ImapFolder.getUIDValidity(folder);
/* 617 */     if (active) {
/* 618 */       return String.format("%s_%d_%d_%d", new Object[] { mbox.getAccountId(), Integer.valueOf(folder.getId()), Integer.valueOf(modseq), Integer.valueOf(uvv) });
/*     */     }
/* 620 */     return String.format("%s:%d:%d:%d", new Object[] { mbox.getAccountId(), Integer.valueOf(folder.getId()), Integer.valueOf(modseq), Integer.valueOf(uvv) });
/*     */   }
/*     */   
/*     */   void serialize(String key, ImapFolder folder)
/*     */   {
/* 625 */     if (!isActiveKey(key)) {
/* 626 */       this.inactiveSessionCache.put(key, folder);
/*     */     } else {
/* 628 */       this.activeSessionCache.put(key, folder);
/*     */     }
/*     */   }
/*     */   
/*     */   ImapFolder deserialize(String key) {
/* 633 */     if (!isActiveKey(key)) {
/* 634 */       return this.inactiveSessionCache.get(key);
/*     */     }
/* 636 */     ImapFolder folder = this.activeSessionCache.get(key);
/* 637 */     return folder;
/*     */   }
/*     */   
/*     */   void updateAccessTime(String key)
/*     */   {
/* 642 */     if (!isActiveKey(key)) {
/* 643 */       this.inactiveSessionCache.updateAccessTime(key);
/*     */     } else {
/* 645 */       this.activeSessionCache.updateAccessTime(key);
/*     */     }
/*     */   }
/*     */   
/*     */   void safeRemoveCache(String key)
/*     */   {
/* 651 */     if (!isActiveKey(key)) {
/* 652 */       this.inactiveSessionCache.remove(key);
/*     */     }
/*     */     else {
/* 655 */       ZimbraLog.imap.warn("Inconsistent active cache entry %s cannot be removed. Client state may not be accurate", new Object[] { key });
/*     */     }
/*     */   }
/*     */   
/*     */   public static boolean isActiveKey(String key) {
/* 660 */     return key.contains("_");
/*     */   }
/*     */   
/*     */   static abstract interface Cache
/*     */   {
/*     */     public abstract void put(String paramString, ImapFolder paramImapFolder);
/*     */     
/*     */     public abstract ImapFolder get(String paramString);
/*     */     
/*     */     public abstract void remove(String paramString);
/*     */     
/*     */     public abstract void updateAccessTime(String paramString);
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/imap/ImapSessionManager.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */